package neu.soft.facade;

import lombok.extern.slf4j.Slf4j;
import neu.soft.constant.FinancialVoucherType;
import neu.soft.entity.FinancialVoucher;
import neu.soft.entity.Good;
import neu.soft.entity.Invoice;
import neu.soft.entity.PayableOrder;
import neu.soft.exception.AppException;
import neu.soft.exception.AppExceptionCodeMsg;
import neu.soft.feignclient.OperationServerFeignClient;
import neu.soft.service.FinancialVoucherService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * @author 李博
 * 成本核算处理,生成财务凭证
 */
@Component
@Slf4j
public class ReceiptAccountingHandler {

    @Autowired
    private OperationServerFeignClient goodFeignClient;

    @Autowired
    private FinancialVoucherService financialVoucherService;

    private static final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    //通过库房的出库明细进行成本核算
    public void accountingOrder(String outOrderId, List<String> code, List<Integer> num, String oid) {

        List<Good> goodList = goodFeignClient.findGoods(code);
        if ("-1".equals(goodList.get(0).getGoodId())) {
            throw new AppException(AppExceptionCodeMsg.QUERY_FAIL);
        }
        if (goodList.size()!=num.size()){
            throw new AppException(AppExceptionCodeMsg.CHECK_FAIL);
        }
        //合成查询到结果的商品的map
        Map<String,BigDecimal> goodMap = goodList.stream().collect(Collectors.toConcurrentMap(Good::getGoodId,Good::getGoodPrice));
        //两个List建立Map，将Map的值的类型转变为BigDecimal
        Map<String, BigDecimal> map = IntStream
                .range(0, code.size())
                .boxed()
                .collect(Collectors.toConcurrentMap(code::get, num::get))
                .entrySet().stream()
                .collect(Collectors.toConcurrentMap(Map.Entry::getKey,e->new BigDecimal(e.getValue())));
        BigDecimal total = new BigDecimal("0.00");
        //合并来计算每一个商品的总金额
        map.forEach((key,value)->goodMap.merge(key,value,BigDecimal::multiply));
        //累加总金额
        BigDecimal reduceRes = goodMap.values().stream().reduce(total, BigDecimal::add);
        FinancialVoucher financialVoucher = new FinancialVoucher();
        financialVoucher.setVoucherType(FinancialVoucherType.LEDGER_RECEIPT_DOCUMENT.getCode());
        financialVoucher.setPrice(reduceRes);
        String info = //生成默认的凭证信息
                "本次财务凭证由单号为" + oid +
                        "的订单产生的单号为"+outOrderId+"的出库单生成。";
        String localDateTime = LocalDateTime.now().format(dateTimeFormatter);
        LocalDateTime parse = LocalDateTime.parse(localDateTime,dateTimeFormatter);
        financialVoucher.setCreatedDate(parse);
        financialVoucher.setInformation(info);
        //设置凭证绑定的订单id，类型为客户核算凭证
        financialVoucher.setOrderId(oid);
        //录入核算凭证
        financialVoucherService.addFinancialVoucher(financialVoucher);
    }

    //基于应付单，与发票成本核算生成财务凭证,传入应付单和发票
    public FinancialVoucher accountingSupply(PayableOrder payableOrder, Invoice invoice){
        if (payableOrder.getPayableCost().compareTo(invoice.getTotalPrice())!=0){
            throw new AppException(AppExceptionCodeMsg.CHECK_FAIL);
        }
        //生成财务凭证
        FinancialVoucher financialVoucher = new FinancialVoucher();
        String orderId = payableOrder.getPayableOrderId().toString();
        financialVoucher.setOrderId(orderId);//设置绑定的应付单id
        financialVoucher.setVoucherType(FinancialVoucherType.CLOSING_DOCUMENT.getCode());//设置凭证类型为企业付款凭证
        financialVoucher.setPrice(payableOrder.getPayableCost());
        String info = //生成默认的凭证信息
                "本次财务凭证由单号为" + orderId +
                        "的应付单生成。";
        financialVoucher.setCreatedDate(payableOrder.getCreatedDate());
        financialVoucher.setInformation(info);
        financialVoucherService.addFinancialVoucher(financialVoucher);
        return financialVoucherService.findByOrderId(orderId);
    }
}
